#pragma once

#include "KKComm.h"
#include "KKRenderI.h"
// #include "KKWindow.h"
#include <algorithm>
#include <functional>
#include <map>
#include <optional>
#include <variant>
#include <vector>

// CSS 属性
using KKUIPropertyValue = std::variant<int, double, std::string, KKColor, KKSpace, KKSpaceColor>;

#define KK_CSS_PROPERTY_WIDTH             "width"         // int or double
#define KK_CSS_PROPERTY_HEIGHT            "height"        // int or double
#define KK_CSS_PROPERTY_LEFT              "left"          // int or double
#define KK_CSS_PROPERTY_TOP               "top"           // int or double
#define KK_CSS_PROPERTY_MARGIN            "margin"        // KKSpace
#define KK_CSS_PROPERTY_PADDING           "padding"       // KKSpace
#define KK_CSS_PROPERTY_BORDER_RADIUS     "border-radius" // int
// #define KK_CSS_PROPERTY_BORDER "border" // width + color + style
#define KK_CSS_PROPERTY_BORDER_COLOR      "border-color" // KKSpaceColor
#define KK_CSS_PROPERTY_BORDER_WIDTH      "border-width" // KKSpace
#define KK_CSS_PROPERTY_BORDER_STYLE      "border-style" // KKSpace
// #define KK_CSS_PROPERTY_FONT "font" //  size + weight + style
#define KK_CSS_PROPERTY_FONT_SIZE         "font-size"         // int or double
#define KK_CSS_PROPERTY_FONT_STYLE        "font-style"        // int
#define KK_CSS_PROPERTY_FONT_FAMILY       "font-family"       // string
#define KK_CSS_PROPERTY_TEXT_ALIGN        "text-align"        // int
#define KK_CSS_PROPERTY_COLOR             "color"             // KKColor, 文本颜色或者前景色
#define KK_CSS_PROPERTY_BACKGROUND_COLOR  "background-color"  // KKColor, 背景颜色或者背景色
#define KK_CSS_PROPERTY_BACKGROUND_IMAGE  "background-image"  // string, 图片路径
#define KK_CSS_PROPERTY_BACKGROUND_REPEAT "background-repeat" // int, 图片填充方式
#define KK_CSS_PROPERTY_CONTENT           "content"           // string, text

struct KKUIProperties
{
    std::string state{"*"}; // *, hover, active, disabled
    // 属性
    std::map<std::string, KKUIPropertyValue> css;

    KKUIProperties(std::string state) { this->state = state; }
};

// Layout 属性
enum KK_LAYOUT_TYPE
{
    KK_LAYOUT_TYPE_NONE = 0, // 默认值, 绝对定位
    KK_LAYOUT_TYPE_FLEX,     // flex 布局
};
struct KKUILayoutProperties
{
    // child layout setting
    KK_LAYOUT_TYPE type{KK_LAYOUT_TYPE_NONE};
    bool flex_direction_row{true};
    bool flex_wrap{false}; // 默认尺寸能填充，则不wrap. 否则就近原则按比例分配
    KK_TEXT_ALIGN flex_content_align_x{KK_TEXT_ALIGN_LEFT};
    KK_TEXT_ALIGN flex_content_align_y{KK_TEXT_ALIGN_LEFT};

    // self in parent setting
    int flex_grow{0}; // 是否自动填充剩余空间, 多个存在时候，按比例分配

    KKUILayoutProperties() {}
};

class KKWindow;

class KKUIBase
{
  public:
    KKUIBase(KKUIBase *parent, int width = 120, int height = 30);
    void *user_data{nullptr};
    KKUIBase *parent{nullptr};

  public:
    // 绘制函数, 一般只绘制自身
    virtual void onRender(KKRenderI *render, KKWindow *win);
    virtual void onRendContent(KKRenderI *render, KKWindow *win);
    // 事件
    virtual void onMouseDown(KKPoint pos, KK_MOUSE_BTN btn);
    virtual void onMouseUp(KKPoint pos, KK_MOUSE_BTN btn);
    virtual void onMouseMove(KKPoint pos);
    virtual void onMouseLeave();
    virtual void onMouseEnter();
    virtual void onMouseWheel(KKPoint pos, int delta);
    virtual void onKeyDown(unsigned char key);
    virtual void onKeyUp(unsigned char key);
    virtual void onKeyChar(unsigned char key);
    virtual void onImeChar(wchar_t key);
    virtual void onCommand(KKEvent event);

    // css 属性，包含为状态
    std::vector<KKUIProperties> properties{};
    // 读写css属性便捷方法
    template <typename T> std::optional<T> getProperty(std::string key, std::string state = "*")
    {
        for (auto &p : properties)
        {
            if (p.state == state)
            {
                auto it = p.css.find(key);
                if (it != p.css.end())
                {
                    return std::get<T>(it->second);
                }
            }
        }
        return std::nullopt;
    }

    using PropertyNotifyCB = std::function<void(KKUIBase *ui, std::string state, std::string key, KKUIPropertyValue val)>;
    PropertyNotifyCB property_notify_cb; // callback notify for css property change
    void setProperty(std::string key, KKUIPropertyValue val, std::string state = "*")
    {
        if (key.length() == 0)
            return;
        for (auto &p : properties)
        {
            if (p.state == state)
            {
                p.css[key] = val;
                if (property_notify_cb)
                    property_notify_cb(this, state, key, val);
            }
        }
    }
    // layout 属性
    KKUILayoutProperties layout{};
    // runtime 属性
    KKRect m_rect{0, 0, 0, 0};         // UI 元素自身的矩形(绝对位置)
    KKRect m_rect_border{0, 0, 0, 0};  // 去掉margin 后的border 矩形
    KKRect m_rect_content{0, 0, 0, 0}; // 去掉marggin,border,padding 后的content 矩形
    void calcRect(KKRect flexForce);   // 计算UI矩形内容值
    // chirldren
    std::vector<KKUIBase *> children{};
    void addChildren(KKUIBase *child);
};